package com.zl.tby.core.base.util;

import com.zl.tby.model.TbyEcologyInfo;
import com.zl.tby.model.TbyMonitoringStation;
import com.zl.tby.service.ITbyEcologyInfoService;
import com.zl.tby.service.ITbyEcologyRealService;
import com.zl.tby.service.ITbyMonitoringStationService;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.Solon;

import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @author changpeng
 * @version 1.0
 * @since 2024/11/4 16:23
 */
@Slf4j
public class EcologySocket {
    public static void start() {
        int[] portArray = {9001, 9002, 9003};
        //int[] portArray = {9002, 9003};
        for (int port : portArray) {
            startByPort(port);
            try {
                Thread.sleep(500);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    public static void startByPort(int port) {
        new Thread(() -> {
            try {
                ServerSocket serverSocket = new ServerSocket(port);
                ITbyMonitoringStationService iTbyMonitoringStationService = Solon.context().getBean(ITbyMonitoringStationService.class);
                ITbyEcologyInfoService iTbyEcologyInfoService = Solon.context().getBean(ITbyEcologyInfoService.class);
                ITbyEcologyRealService tbyEcologyRealService = Solon.context().getBean(ITbyEcologyRealService.class);
                while (true) {
                    if (serverSocket.isBound() && !serverSocket.isClosed()) {
                        log.info(port + ": ServerSocket已连接");
                    } else {
                        log.info(port + ": ServerSocket已关闭 正在重新打开链接");
                        serverSocket = new ServerSocket(port);
                    }
                    Socket clientSocket = serverSocket.accept();
                    if (clientSocket.isConnected()) {
                        log.info(port + ": 客户端已连接");
                    } else {
                        log.info(port + ": 客户端连接失败");
                        serverSocket.close();
                        serverSocket = new ServerSocket(port);
                    }

                    InputStream inputStream = null;
                    OutputStream outputStream = null;
                    try {
                        inputStream = clientSocket.getInputStream();
                        outputStream = clientSocket.getOutputStream();

                        log.info(port + "：开始接收");
                        byte[] bytes = new byte[4096];
                        int len;
                        StringBuilder sb = new StringBuilder();

                        while ((len = inputStream.read(bytes)) != -1) {
                            sb.append(new String(bytes, 0, len));
                            String temp = sb.toString();
                            log.info(port + "、接到消息：" + temp);
                            if (!temp.startsWith("#")) {
                                log.info(port + "、不是#开头，跳出循环");
                                break;
                            }
                            if (temp.indexOf("GG") > -1) {
                                log.info(port + "、跳出循环: ");
                                break;
                            }
                        }
                        String receivedMessage = sb.toString();

                        /*byte[] buffer = new byte[4096];
                        int bytesRead = inputStream.read(buffer);
                        String receivedMessage = new String(buffer, 0, bytesRead);*/
                        log.info(port + "、收到最终结果：" + receivedMessage);

                        // 调用方法处理假数据和数据库操作
                        processEcologyData(iTbyMonitoringStationService, iTbyEcologyInfoService, tbyEcologyRealService, receivedMessage, port);

                        // 发送响应数据给客户端
                        String responseMessage = port + "、已收到消息";
                        outputStream.write(responseMessage.getBytes());

                    } catch (Exception ex) {
                        ex.printStackTrace();
                        log.error(port + "处理数据异常信息：" + ex.getMessage());
                    } finally {
                        try {
                            // 关闭连接
                            clientSocket.close();
                            System.out.println("ServerSocket关闭成功");
                        } catch (Exception e) {
                            log.error("ServerSocket关闭错误：" + e);
                        }
                        try {
                            if (inputStream != null) {
                                inputStream.close();
                            }
                            if (outputStream != null) {
                                outputStream.close();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    private static void processEcologyData(ITbyMonitoringStationService monitoringStationService, ITbyEcologyInfoService ecologyInfoService, ITbyEcologyRealService tbyEcologyRealService, String receivedMessage, int port) throws Exception {
        TbyEcologyInfo tbyEcologyInfo = createEcologyInfo(monitoringStationService, receivedMessage, port);
        if (tbyEcologyInfo == null) {
            return;
        }
        // 添加实时数据
        tbyEcologyRealService.add(tbyEcologyInfo);
        if (tbyEcologyInfo.getStationId().compareTo(0L) == 0) {
            // 没有获取到设备，直接存储
            ecologyInfoService.add(tbyEcologyInfo);
            return;
        }
        // 查询数据库中是否有匹配项
        if (isEcologyInfoExists(ecologyInfoService, tbyEcologyInfo)) {
            updateEcologyInfo(ecologyInfoService, tbyEcologyInfo);
        } else {
            ecologyInfoService.add(tbyEcologyInfo);
        }
    }

    private static TbyEcologyInfo createEcologyInfo(ITbyMonitoringStationService iTbyMonitoringStationService, String receivedMessage, int port) throws Exception {
        long deviceCodeDecimal = 0;
        long luxDecimal = 0;
        long oxygenDecimal = 0;
        long pmOneDecimal = 0;
        long pmTwoDecimal = 0;
        double beamFinalRounded = 0;
        double rainFinalRounded = 0;
        double tempFinalRounded = 0;
        double humidityFinalRounded = 0;
        double windSpeedFinalRounded = 0;
        double pressureFinalRounded = 0;
        long windDirectionDecimal = 0;
        Date processedDate = null;
        String deviceCodeStr = "";
        // 1. 验证报文头
        if (receivedMessage.startsWith("#")) {
            // 2. 截取设备编号（从 1 开始的 8 个字符）
            String deviceCodeHex = receivedMessage.substring(1, 5);
            deviceCodeDecimal = parseHexToDecimal(deviceCodeHex);
            deviceCodeStr = "C602400"+ deviceCodeDecimal;
            System.out.println("设备编号（十六进制）: " + deviceCodeHex);
            System.out.println("设备编号（十进制）: " + deviceCodeStr);

            // 3. 截取日期部分
            String dateHex = receivedMessage.substring(9, 21);
            processedDate = processDate(dateHex);
            System.out.println("处理后的 Date 对象: " + processedDate);

            // 4. 截取气温-环温部分
            String tempHex = receivedMessage.substring(21, 25);
            tempFinalRounded = processHexValue(tempHex, 0.1);
            System.out.println("气温-环温最终值: " + tempFinalRounded);

            // 5. 截取湿度-环湿部分
            String humidityHex = receivedMessage.substring(49, 53);
            humidityFinalRounded = processHexValue(humidityHex, 0.1);
            System.out.println("湿度-环湿最终值: " + humidityFinalRounded);

            // 6. 截取降雨量-雨量间隔累计部分
            String rainHex = receivedMessage.substring(121, 125);
            rainFinalRounded = processHexValue(rainHex, 0.1);
            System.out.println("降雨量-雨量间隔累计最终值: " + rainFinalRounded);

            // 7. 截取紫外辐射部分
            String luxHex = receivedMessage.substring(101, 105);
            luxDecimal = parseHexToDecimal(luxHex);
            System.out.println("紫外辐射（十进制）: " + luxDecimal);

            // 8. 截取pm2.5部分
            String pmOneHex = receivedMessage.substring(201, 205);
            pmOneDecimal = parseHexToDecimal(pmOneHex);
            System.out.println("pm2.5（十进制）: " + pmOneDecimal);

            // 9. 截取pm10部分
            String pmTwoHex = receivedMessage.substring(205, 209);
            pmTwoDecimal = parseHexToDecimal(pmTwoHex);
            System.out.println("pm10（十进制）: " + pmTwoDecimal);

            // 10. 截取风速部分
            String windSpeedHex = receivedMessage.substring(109, 113);
            windSpeedFinalRounded = processHexValue(windSpeedHex, 0.1);
            System.out.println("风速最终值: " + windSpeedFinalRounded);

            // 11. 截取风向部分
            String windDirectionHex = receivedMessage.substring(105, 109);
            windDirectionDecimal = parseHexToDecimal(windDirectionHex);
            System.out.println("风向（十进制）: " + windDirectionDecimal);

            // 12. 截取负氧离子部分
            String oxygenHex = receivedMessage.substring(209, 217);
            oxygenDecimal = parseHexToDecimal(oxygenHex);
            System.out.println("负氧离子（十进制）: " + oxygenDecimal);

            // 13. 截取气压部分
            String pressure = receivedMessage.substring(73, 77);
            pressureFinalRounded = processHexValue(pressure, 0.1);
            System.out.println("气压最终值: " + pressureFinalRounded);

            // 14. 截取光照
            String beam = receivedMessage.substring(193, 197);
            beamFinalRounded = processHexValue(beam, 10);
            System.out.println("光照（十进制）: " + beamFinalRounded);

        } else {
            log.error(port + "、报文格式错误，未以 '#' 开头，" + receivedMessage);
            return null;
        }
        // 数据在此处整理下
        String deviceCode = deviceCodeStr; // 设备编号
        BigDecimal temperature = BigDecimal.valueOf(tempFinalRounded); // 气温-环温
        BigDecimal humidity = BigDecimal.valueOf(humidityFinalRounded); // 湿度-环湿
        BigDecimal rain = BigDecimal.valueOf(rainFinalRounded); // 降雨量-雨量间隔累计
        Integer lux = Integer.valueOf((int) luxDecimal); // 紫外辐射值
        Integer oxygen = Integer.valueOf((int) oxygenDecimal); // 负氧离子值
        Integer pmOne = Integer.valueOf((int) pmOneDecimal); // PM2.5 值
        Integer pmTwo = Integer.valueOf((int) pmTwoDecimal); // PM10 值
        BigDecimal windSpeed = BigDecimal.valueOf(windSpeedFinalRounded); // 风速值
        Integer windDirection = Integer.valueOf((int) windDirectionDecimal); // 风向
        BigDecimal pressure = BigDecimal.valueOf(pressureFinalRounded); // 气压
        Integer beam = Integer.valueOf((int) beamFinalRounded); // 光照

        // 根据设备编号查出设备id
        List<TbyMonitoringStation> monitoringStationList = iTbyMonitoringStationService.selectByDeviceCode(deviceCode);
        Long stationId = monitoringStationList != null && monitoringStationList.size() > 0 ? monitoringStationList.get(0).getId() : 0L;

        // 报文解析之后进行赋值
        TbyEcologyInfo tbyEcologyInfo = new TbyEcologyInfo();
        tbyEcologyInfo.setStationId(stationId);
        tbyEcologyInfo.setReportDate(processedDate);
        tbyEcologyInfo.setTemperature(temperature);
        tbyEcologyInfo.setHumidity(humidity);
        tbyEcologyInfo.setRain(rain);
        tbyEcologyInfo.setLux(lux);
        tbyEcologyInfo.setOxygen(oxygen);
        tbyEcologyInfo.setPmOne(pmOne);
        tbyEcologyInfo.setPmTwo(pmTwo);
        tbyEcologyInfo.setWindSpeed(windSpeed);
        tbyEcologyInfo.setWindDirection(windDirection);
        tbyEcologyInfo.setPressure(pressure);
        tbyEcologyInfo.setBeam(beam);
        tbyEcologyInfo.setContent(receivedMessage);
        return tbyEcologyInfo;
    }

    //查询数据库中是否存在数据
    private static boolean isEcologyInfoExists(ITbyEcologyInfoService iTbyEcologyInfoService, TbyEcologyInfo tbyEcologyInfo) {
        List<TbyEcologyInfo> tbyEcologyInfoList = iTbyEcologyInfoService.selectByIdTime(tbyEcologyInfo.getStationId(), tbyEcologyInfo.getReportDate());
        return !tbyEcologyInfoList.isEmpty();
    }

    //降雨量累加之后修改
    private static void updateEcologyInfo(ITbyEcologyInfoService iTbyEcologyInfoService, TbyEcologyInfo tbyEcologyInfo) {
        List<TbyEcologyInfo> tbyEcologyInfoList = iTbyEcologyInfoService.selectByIdTime(tbyEcologyInfo.getStationId(), tbyEcologyInfo.getReportDate());
        if (!tbyEcologyInfoList.isEmpty()) {
            // 降雨量累加
            BigDecimal oldRain = tbyEcologyInfoList.get(0).getRain();
            BigDecimal sumRain = tbyEcologyInfo.getRain().add(oldRain);
            tbyEcologyInfo.setRain(sumRain);
            tbyEcologyInfo.setId(tbyEcologyInfoList.get(0).getId());
            iTbyEcologyInfoService.update(tbyEcologyInfo);
        }
    }

    private static short parseHexToDecimal(String hex) {
        //return Long.parseLong(hex, 16);
        return (short)Integer.parseInt(hex, 16);
    }

    private static double processHexValue(String hexValue, double precision) {
        long decimalValue = parseHexToDecimal(hexValue);
        double adjustedValue = decimalValue * precision; // 直接乘以精度
        BigDecimal finalValue = new BigDecimal(adjustedValue);
        return finalValue.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue(); // 保留一位小数
    }

    private static Date processDate(String dateHex) {
        // 解析日期
        String year = "20" + dateHex.substring(0, 2); // 添加前缀 "20"
        String month = dateHex.substring(2, 4); // 月
        String day = dateHex.substring(4, 6); // 日
        String hour = dateHex.substring(6, 8); // 时

        // 构建完整的日期字符串
        String formattedDateString = String.format("%s-%s-%s %s:%s:%s", year, month, day, hour, "00", "00");
        // 将字符串转换为 Date 对象
        Date date = null;
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            date = dateFormat.parse(formattedDateString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date; // 返回处理后的 Date 对象
    }

    public static void main(String[] args) {
        //String receivedMessage = "#0111030C241214085900FFFF00000000000000000000FFE403DB0000000000000000000022D50000000000000000000000000002015D0005000700070000000000000000000000000000000000030000000000000000000000000000000000080000007D0049005200003822GG";
        String receivedMessage = "#0111030C241214055900FFFE00000000000000000000FFEC03E80000000000000000000022C8000000000000000000000000000001400006000600050000000000000000000000000000000000000000000000000000000000000000000000000000007D0046004E00003C6CGG";
        long deviceCodeDecimal = 0;
        long luxDecimal = 0;
        long oxygenDecimal = 0;
        long pmOneDecimal = 0;
        long pmTwoDecimal = 0;
        double beamFinalRounded = 0;
        double rainFinalRounded = 0;
        double tempFinalRounded = 0;
        double humidityFinalRounded = 0;
        double windSpeedFinalRounded = 0;
        double pressureFinalRounded = 0;
        long windDirectionDecimal = 0;
        Date processedDate = null;
        String deviceCodeStr = "";
        // 1. 验证报文头
        if (receivedMessage.startsWith("#")) {
            // 2. 截取设备编号（从 1 开始的 8 个字符）
            String deviceCodeHex = receivedMessage.substring(1, 5);
            deviceCodeDecimal = parseHexToDecimal(deviceCodeHex);
            deviceCodeStr = "C602400"+ deviceCodeDecimal;
            System.out.println("设备编号（十六进制）: " + deviceCodeHex);
            System.out.println("设备编号（十进制）: " + deviceCodeStr);

            // 3. 截取日期部分
            String dateHex = receivedMessage.substring(9, 21);
            processedDate = processDate(dateHex);
            System.out.println("处理后的 Date 对象: " + processedDate);

            // 4. 截取气温-环温部分
            String tempHex = receivedMessage.substring(21, 25);
            tempFinalRounded = processHexValue(tempHex, 0.1);
            System.out.println("气温-环温最终值: " + tempHex + "  " + tempFinalRounded);

            // 5. 截取湿度-环湿部分
            String humidityHex = receivedMessage.substring(49, 53);
            humidityFinalRounded = processHexValue(humidityHex, 0.1);
            System.out.println("湿度-环湿最终值: " + humidityFinalRounded);

            // 6. 截取降雨量-雨量间隔累计部分
            String rainHex = receivedMessage.substring(121, 125);
            rainFinalRounded = processHexValue(rainHex, 0.1);
            System.out.println("降雨量-雨量间隔累计最终值: " + rainFinalRounded);

            // 7. 截取紫外辐射部分
            String luxHex = receivedMessage.substring(101, 105);
            luxDecimal = parseHexToDecimal(luxHex);
            System.out.println("紫外辐射（十进制）: " + luxDecimal);

            // 8. 截取pm2.5部分
            String pmOneHex = receivedMessage.substring(201, 205);
            pmOneDecimal = parseHexToDecimal(pmOneHex);
            System.out.println("pm2.5（十进制）: " + pmOneDecimal);

            // 9. 截取pm10部分
            String pmTwoHex = receivedMessage.substring(205, 209);
            pmTwoDecimal = parseHexToDecimal(pmTwoHex);
            System.out.println("pm10（十进制）: " + pmTwoDecimal);

            // 10. 截取风速部分
            String windSpeedHex = receivedMessage.substring(109, 113);
            windSpeedFinalRounded = processHexValue(windSpeedHex, 0.1);
            System.out.println("风速最终值: " + windSpeedFinalRounded);

            // 11. 截取风向部分
            String windDirectionHex = receivedMessage.substring(105, 109);
            windDirectionDecimal = parseHexToDecimal(windDirectionHex);
            System.out.println("风向（十进制）: " + windDirectionDecimal);

            // 12. 截取负氧离子部分
            String oxygenHex = receivedMessage.substring(209, 217);
            oxygenDecimal = parseHexToDecimal(oxygenHex);
            System.out.println("负氧离子（十进制）: " + oxygenDecimal);

            // 13. 截取气压部分
            String pressure = receivedMessage.substring(73, 77);
            pressureFinalRounded = processHexValue(pressure, 0.1);
            System.out.println("气压最终值: " + pressureFinalRounded);

            // 14. 截取光照
            String beam = receivedMessage.substring(193, 197);
            beamFinalRounded = processHexValue(beam, 10);
            System.out.println("光照（十进制）: " + beamFinalRounded);

        }
    }
}
